<?php

declare(strict_types=1);

namespace App\Controller;

use Hyperf\Apidog\Annotation\ApiController;
use Hyperf\Apidog\Annotation\PostApi;
use Hyperf\Apidog\Annotation\GetApi;
use Hyperf\Apidog\Annotation\FormData;
use Hyperf\Apidog\Annotation\Body;
use Hyperf\Apidog\Annotation\PutApi;
use Hyperf\Utils\Arr;
use Hyperf\Context\Context;
use App\Model\AdminMenu;
use Hyperf\DbConnection\Db;

/**
 * @ApiController(prefix="menus", tag="权限菜单", server="backend-api")
 */
class AdminMenusController extends AdminController
{
    /**
     * @GetApi(path="tree", description="菜单树")
     */
    public function tree()
    {
        $raw = AdminMenu::getRaw();
        return $this->adminResponse(200, '请求成功', [
            'tree' => AdminMenu::buildTree($raw),
            'options' => AdminMenu::buildSelectOptions($raw),
        ]);
    }

    /**
     * @PostApi(path="save", description="创建/编辑菜单")
     * @FormData(key="id|id", rule="integer|exists:admin_menus")
     * @FormData(key="parent_id|父级id", rule="required|integer|cb_ruleExistsMenuParentId")
     * @FormData(key="name|标题", rule="")
     * @FormData(key="order|排序", rule="integer")
     * @FormData(key="route|前端路由数据JSON", rule="required|json")
     * @FormData(key="route|前端路由数据JSON", rule="required|json")
     * @FormData(key="include_sites|所属站点", rule="")
     * @FormData(key="exclude_sites|排除站点", rule="")
     */
    public function save()
    {
        $validator_data = Context::get('validator.data');
        $AdminMenu = AdminMenu::firstOrNew(['id' => Arr::get($validator_data, 'id')]);
        isset($validator_data['include_sites']) && $validator_data['include_sites'] = explode(',', $validator_data['include_sites']);
        isset($validator_data['exclude_sites']) && $validator_data['exclude_sites'] = explode(',', $validator_data['exclude_sites']);
        $AdminMenu->fill($validator_data)->save();
        return $this->adminResponse(200, '请求成功', $AdminMenu->toArray());
    }

    /**
     * 验证规则：父级id是否有效
     * @param $attribute
     * @param $value
     * @return bool|string
     */
    public function ruleExistsMenuParentId($attribute, $value)
    {
        if(!$value)
            return true;
        $count = AdminMenu::where('id', $value)->count();
        return $count ? true : "无效的";
    }

    /**
     * 验证规则：名称唯一
     * @param $attribute
     * @param $value
     * @return bool|string
     */
    public function ruleUniqueMenuName($attribute, $value)
    {
        $AdminMenu = AdminMenu::where('name', $value)->first(['id', 'name']);
        return $AdminMenu->id && $AdminMenu->id != $this->request->post('id', 0) ? "{$AdminMenu->name} 已存在" : true;
    }

    /**
     * @PutApi(path="tree", description="更新菜单树")
     * @Body(rules={
     *     "list|菜单数组": "required|array",
     *     "list.*.id|菜单id": "required|integer|exists:admin_menus",
     *     "list.*.parent_id|父级id": "required|integer|cb_ruleExistsMenuParentId",
     * })
     */
    public function updateTree()
    {
        $validator_data = Context::get('validator.data');
        $list = Arr::get($validator_data, 'list', []);
        if (!is_array($list) || !$list)
            return $this->adminResponse(400, '菜单不能为空');

        Db::transaction(function () use ($list) {
            $ids = [];
            $parent_order = [];
            foreach ($list as $k => $v) {
                $order = Arr::get($parent_order, $v['parent_id'], 0);
                AdminMenu::query()->where('id', $v['id'])->update([
                    'parent_id' => $v['parent_id'],
                    'order' => $order,
                ]);
                Arr::set($parent_order, $v['parent_id'], ++$order);
                $ids[] = $v['id'];
            }

            AdminMenu::query()->whereNotIn('id', $ids)->delete();
        });

        return $this->adminResponse(200, '请求成功');
    }
}
